package com.yunduansing.demo.service.impl;

import com.yunduansing.demo.entity.DictionaryEntity;
import com.yunduansing.demo.exception.RecordExistsException;
import com.yunduansing.demo.mapper.DictionaryMapper;
import com.yunduansing.demo.model.common.PageRequestModel;
import com.yunduansing.demo.model.common.PageResultModel;
import com.yunduansing.demo.model.dictionary.DictionaryPageRequestModel;
import com.yunduansing.demo.model.dictionary.DictionaryTreeModel;
import com.yunduansing.demo.service.DictionaryService;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

/**
 * <p>
 * 字典表 服务实现类
 * </p>
 *
 * @author yunduansing
 * @since 2020-05-24
 */
@Service
public class DictionaryServiceImpl extends ServiceImpl<DictionaryMapper, DictionaryEntity>
        implements DictionaryService {
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private DictionaryMapper dictionaryMapper;
    private final String CACHE_PRFIX="Dictionary:";

    @Override
    public PageResultModel<DictionaryEntity> getPage(PageRequestModel model) {
        var wrapper = new QueryWrapper<DictionaryEntity>();
        if (!StringUtils.isEmpty(model.getKey())) {
            wrapper.or().like("name", model.getKey()).or().like("code", model.getKey());
        }
        Page<DictionaryEntity> page = new Page<>(model.getCurrent(), model.getPageSize());
        var data = page(page);
        return new PageResultModel<DictionaryEntity>(data.getTotal(), data.getRecords());
    }

    @Override
    public boolean create(DictionaryEntity entity) throws RecordExistsException {
        var exists = existsByPidKey(entity.getPid(), entity.getKey());
        if (exists.stream().filter(x -> x.getKey().contains(entity.getKey())).count() > 0)
            throw new RecordExistsException("相同父级下已存在key为：" + entity.getKey() + "的字典。");
        return save(entity);
    }

    @Override
    public boolean update(DictionaryEntity entity) throws RecordExistsException {
        var exists = existsByPidKey(entity.getPid(), entity.getKey());
        if (exists.stream().filter(x -> x.getKey().contains(entity.getKey()) && x.getId() != entity.getId())
                .count() > 0)
            throw new RecordExistsException("已存在key为：" + entity.getKey() + "的字典。");
        return update(entity);
    }

    private List<DictionaryEntity> existsByPidKey(int pid, String key) {
        var wrapper = new QueryWrapper<DictionaryEntity>();
        wrapper.eq("pid", pid).like("`key`", key);
        return list(wrapper);
    }

    @Override
    public List<DictionaryTreeModel> getTree(DictionaryPageRequestModel model) {
        var data = this.list();
        if (model.getCategoryId() > 0) {
            data = data.stream().filter(x -> x.getCategoryId() == model.getCategoryId()).collect(Collectors.toList());
        }
        return generateTree(0, data);
    }

    private List<DictionaryTreeModel> generateTree(int pid, List<DictionaryEntity> entities) {
        var data = entities.stream().filter(x -> x.getPid() == pid).collect(Collectors.toList());
        Collections.sort(data);
        var list = new ArrayList<DictionaryTreeModel>();
        if (data.size() > 0) {
            for (var item : data) {
                if (item.getStatus()) {
                    list.add(new DictionaryTreeModel(item, generateTree(item.getId(), entities)));
                }
            }
        }
        return list;
    }

    @Override
    public List<DictionaryTreeModel> getAll() {
        var cache=redisTemplate.opsForValue().get(CACHE_PRFIX+"All:WithCateCode");
        if(cache!=null) return (ArrayList<DictionaryTreeModel>)cache;
        var allData= dictionaryMapper.getAll();
        redisTemplate.opsForValue().set(CACHE_PRFIX+"All:WithCateCode", allData);
        return allData;
    }

}
